package rexsee.security;

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.DSAPrivateKeySpec;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

import rexsee.core.application.RexseeApplication;
import rexsee.core.browser.Browser;
import rexsee.core.browser.clazz.JavascriptInterface;

public class RexseeKeyPairGenerator implements JavascriptInterface {

	public static final String INTERFACE_NAME = "KeyPairGenerator";
	@Override
	public String getInterfaceName() {
		return mBrowser.application.resources.prefix + INTERFACE_NAME;
	}
	@Override
	public JavascriptInterface getInheritInterface(Browser childBrowser) {
		return this;
	}
	@Override
	public JavascriptInterface getNewInterface(Browser childBrowser) {
		return new RexseeKeyPairGenerator(childBrowser);
	}

	private final Browser mBrowser;

	public RexseeKeyPairGenerator(Browser browser) {
		mBrowser = browser;
	}

	private String mPublicKey = null;;
	private String mPrivateKey = null;

	//JavaScript interface

	public boolean generateRSAKeyPair(int keySize) {
		if (keySize < 256 || keySize > 2048 || keySize % 64 != 0) return false;
		try {
			KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RexseeSecurity.ALGORITHM_RSA);
			keyPairGen.initialize(keySize);
			KeyPair keyPair = keyPairGen.generateKeyPair();
			mPublicKey = RexseeSecurity.key2string_(keyPair.getPublic());
			mPrivateKey = RexseeSecurity.key2string_(keyPair.getPrivate());
			return true;
		} catch (Exception e) {
			return false;
		}
	}
	public boolean generateDSAKeyPair(int keySize) {
		if (keySize < 256 || keySize > 2048 || keySize % 64 != 0) return false;
		try {
			KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RexseeSecurity.ALGORITHM_DSA);
			keyPairGen.initialize(keySize);
			KeyPair keyPair = keyPairGen.generateKeyPair();
			mPublicKey = RexseeSecurity.key2string_(keyPair.getPublic());
			mPrivateKey = RexseeSecurity.key2string_(keyPair.getPrivate());
			return true;
		} catch (Exception e) {
			return false;
		}
	}
	public String getPublicKey() {
		return mPublicKey;
	}
	public String getPrivateKey() {
		return mPrivateKey;
	}

	//User-defined key

	/* RSA Sample Data:
	 * String modulus = "10103166745709600780215616551837697832816413714471062522342538060943596036859967333870827790358555455232243383580565187280643159050869924436081447583051139";   
	 * String publicExponent = "65537";   
	 * String privateExponet = "367979294475011322800474185715497882523349856362702385535371444397399388741997039894583483410120364529325888461124714276674612930833020362278754665756193";   
	*/
	public String generateRsaPublicKey(String modulus, String publicExponent) {
		try {
			BigInteger m = new BigInteger(modulus);
			BigInteger e = new BigInteger(publicExponent);
			PublicKey key = KeyFactory.getInstance(RexseeSecurity.ALGORITHM_RSA).generatePublic(new RSAPublicKeySpec(m, e));
			return RexseeSecurity.key2string_(key);
		} catch (Exception e) {
			return RexseeApplication.EXCEPTION_PREFIX + e.getLocalizedMessage();
		}
	}
	public String generateRsaPrivateKey(String modulus, String privateExponent) {
		try {
			BigInteger m = new BigInteger(modulus);
			BigInteger e = new BigInteger(privateExponent);
			PrivateKey key = KeyFactory.getInstance(RexseeSecurity.ALGORITHM_RSA).generatePrivate(new RSAPrivateKeySpec(m, e));
			return RexseeSecurity.key2string_(key);
		} catch (Exception e) {
			return RexseeApplication.EXCEPTION_PREFIX + e.getLocalizedMessage();
		}
	}

	public String generateDsaPublicKey(String prime, String subPrime, String base, String publicKey) {
		try {
			BigInteger p = new BigInteger(prime);
			BigInteger q = new BigInteger(subPrime);
			BigInteger g = new BigInteger(base);
			BigInteger y = new BigInteger(publicKey);
			PublicKey key = KeyFactory.getInstance(RexseeSecurity.ALGORITHM_DSA).generatePublic(new DSAPublicKeySpec(y, p, q, g));
			return RexseeSecurity.key2string_(key);
		} catch (Exception e) {
			return RexseeApplication.EXCEPTION_PREFIX + e.getLocalizedMessage();
		}
	}
	public String generateDsaPrivateKey(String prime, String subPrime, String base, String privateKey) {
		try {
			BigInteger p = new BigInteger(prime);
			BigInteger q = new BigInteger(subPrime);
			BigInteger g = new BigInteger(base);
			BigInteger x = new BigInteger(privateKey);
			PrivateKey key = KeyFactory.getInstance(RexseeSecurity.ALGORITHM_DSA).generatePrivate(new DSAPrivateKeySpec(x, p, q, g));
			return RexseeSecurity.key2string_(key);
		} catch (Exception e) {
			return RexseeApplication.EXCEPTION_PREFIX + e.getLocalizedMessage();
		}
	}

}
